package com.apanal.qlife.common.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.apanal.qlife.common.constants.Constants;
import com.apanal.qlife.common.util.DateUtil.DateStyle;

/**
 * 文件操作工具类
 * 
 * @author shuliangxing
 * 
 * @date 2015-1-15上午9:48:33
 */
public class FileOperateUtil {
	/**
	 * 实际名字
	 */
	public static final String REALNAME = "realName";

	/**
	 * 存储名字
	 */
	public static final String STORENAME = "storeName";

	/**
	 * 存储路径
	 */
	public static final String STOREPATH = "storePath";

	/**
	 * 大小,单位B
	 */
	public static final String SIZE = "size";

	/**
	 * 文件后缀
	 */
	public static final String SUFFIX = "suffix";

	/**
	 * contentType
	 */
	public static final String CONTENTTYPE = "contentType";

	/**
	 * 创建时间
	 */
	public static final String CREATETIME = "createTime";

	/**
	 * 默认上传目录
	 */
	public static final String DEFAULT_UPLOADDIR = "upload";

	/**
	 * 模板下载目录
	 */
	// public static final String DOWNLOADDIR = "template/";

	private static final Logger logger = Logger
			.getLogger(FileOperateUtil.class);

	/**
	 * 将上传的文件进行重命名
	 * 
	 * @param name
	 * @return
	 */
	public static String rename(String name) {

		String now = DateUtil
				.dateToString(new Date(), DateStyle.YYYYMMDDHHMMSS);
		// Long random = (long) (Math.random() * now);
		String random = TextFomat.getRandomStr(6);
		String fileName = now + random;

		if (name.indexOf(".") != -1) {
			fileName += name.substring(name.lastIndexOf("."));
		}

		return fileName;
	}

	/**
	 * 压缩后的文件名
	 * 
	 * @param name
	 * @return
	 */
	public static String zipName(String name) {
		String prefix = "";
		if (name.indexOf(".") != -1) {
			prefix = name.substring(0, name.lastIndexOf("."));
		} else {
			prefix = name;
		}
		return prefix + ".zip";
	}

	public static String getFileSuffix(String name) {
		if (name.lastIndexOf(".") != -1) {
			return name.substring(name.lastIndexOf(".") + 1);
		}
		return "";
	}

	/**
	 * 把文件按分类和日期保存到服务器,最终路径为:服务器上传跟路径+文件分类路径+yyyy/MMdd/
	 * 
	 * @param basePath
	 *            服务器上传跟路径
	 * @param typePath
	 *            文件分类路径
	 * @param request
	 * @return 保存信息
	 * @throws IOException
	 */
	public static List<Map<String, Object>> upload(String basePath,
			String typePath, HttpServletRequest request) throws IOException {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		Date date = new Date();

		MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) request;
		Map<String, MultipartFile> fileMap = mRequest.getFileMap();

		// 上传路径后面部分
		String sufPath = typePath + "/" + getUploadPathByDate(date);
		// 如果服务器上传跟路径为空则使用默认路径
		if (StringUtils.isEmpty(basePath)) {
			basePath = DEFAULT_UPLOADDIR;
		}
		// 如果服务器上传跟路径不是绝对路径,则把文件存储到项目根目录下
		if (!basePath.startsWith("/")) {
			basePath = request.getSession().getServletContext()
					.getRealPath(basePath);
		}
		// 实际上传途径
		String realPath = basePath + "/" + sufPath;
		File file = new File(realPath);

		if (!file.exists()) {
			// 可能创建多级目录,mkdir()不能创建多级目录,如果父目录不存在会返回false
			file.mkdirs();
		}

		Iterator<String> it = fileMap.keySet().iterator();
		while (it.hasNext()) {
			Map<String, Object> map = null;
			MultipartFile mFile = fileMap.get(it.next());
			if (!mFile.isEmpty()) {
				map = new HashMap<String, Object>();
				String fileName = mFile.getOriginalFilename();

				String storeName = rename(fileName);

				file = new File(realPath, storeName);
				mFile.transferTo(file);

				// 固定参数值对
				map.put(FileOperateUtil.REALNAME, fileName);
				map.put(FileOperateUtil.STORENAME, storeName);
				map.put(FileOperateUtil.STOREPATH, sufPath + storeName);
				map.put(FileOperateUtil.SIZE, mFile.getSize());
				map.put(FileOperateUtil.SUFFIX, getFileSuffix(fileName));
				map.put(FileOperateUtil.CONTENTTYPE, mFile.getContentType());
				map.put(FileOperateUtil.CREATETIME, date);

				list.add(map);
			} else {
				logger.info("上传文件为空");
			}

		}
		return list;
	}

	/**
	 * 上传文件
	 * 
	 * @param request
	 * @param params
	 * @param values
	 * @return
	 * @throws IOException
	 * @throws Exception
	 */
	/*
	 * public static List<Map<String, Object>> upload(HttpServletRequest
	 * request, String[] params, Map<String, Object[]> values) throws
	 * IOException {
	 * 
	 * List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
	 * 
	 * MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest)
	 * request; Map<String, MultipartFile> fileMap = mRequest.getFileMap();
	 * 
	 * 
	 * String uploadDir = request.getSession().getServletContext()
	 * .getRealPath("/") + FileOperateUtil.UPLOADDIR;
	 * 
	 * String uploadDir = Constants.FILE_UPLOAD_PATH + getUploadPathByDate(new
	 * Date()); File file = new File(uploadDir);
	 * 
	 * if (!file.exists()) { file.mkdir(); }
	 * 
	 * String fileName = null; int i = 0; for (Iterator<Map.Entry<String,
	 * MultipartFile>> it = fileMap.entrySet() .iterator(); it.hasNext(); i++) {
	 * 
	 * Map.Entry<String, MultipartFile> entry = it.next(); MultipartFile mFile =
	 * entry.getValue();
	 * 
	 * fileName = mFile.getOriginalFilename();
	 * 
	 * String storeName = rename(fileName);
	 * 
	 * String noZipName = uploadDir + storeName; String zipName =
	 * zipName(noZipName);
	 * 
	 * // 上传成为压缩文件 ZipOutputStream outputStream = new ZipOutputStream( new
	 * BufferedOutputStream(new FileOutputStream(zipName)));
	 * outputStream.putNextEntry(new ZipEntry(fileName));
	 * outputStream.setEncoding("GBK");
	 * 
	 * FileCopyUtils.copy(mFile.getInputStream(), outputStream);
	 * 
	 * Map<String, Object> map = new HashMap<String, Object>(); // 固定参数值对
	 * map.put(FileOperateUtil.REALNAME, zipName(fileName));
	 * map.put(FileOperateUtil.STORENAME, zipName(storeName));
	 * map.put(FileOperateUtil.SIZE, new File(zipName).length());
	 * map.put(FileOperateUtil.SUFFIX, "zip");
	 * map.put(FileOperateUtil.CONTENTTYPE, "application/octet-stream");
	 * map.put(FileOperateUtil.CREATETIME, new Date());
	 * 
	 * // 自定义参数值对 for (String param : params) { map.put(param,
	 * values.get(param)[i]); }
	 * 
	 * result.add(map); } return result; }
	 */

	/**
	 * 下载
	 * 
	 * @param request
	 * @param response
	 * @param storePathAndName
	 *            文件存储路径和名称
	 * @param contentType
	 * @param realName
	 *            前端显示的下载名称
	 * @throws IOException
	 */
	public static void download(HttpServletRequest request,
			HttpServletResponse response, String storePathAndName,
			String contentType, String realName) throws IOException {
		response.setContentType("text/html;charset=UTF-8");
		request.setCharacterEncoding("UTF-8");
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;

		/*
		 * String ctxPath = request.getSession().getServletContext()
		 * .getRealPath("/") + Constants.PATH_TEMPLATE;
		 */
		String downLoadPath = Constants.FILE_UPLOAD_PATH + storePathAndName;

		long fileLength = new File(downLoadPath).length();

		response.setContentType(contentType);
		response.setHeader("Content-disposition", "attachment; filename="
				+ new String(realName.getBytes("utf-8"), "ISO8859-1"));
		response.setHeader("Content-Length", String.valueOf(fileLength));

		bis = new BufferedInputStream(new FileInputStream(downLoadPath));
		bos = new BufferedOutputStream(response.getOutputStream());
		byte[] buff = new byte[2048];
		int bytesRead;
		while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
			bos.write(buff, 0, bytesRead);
		}
		bis.close();
		bos.close();
	}

	/**
	 * 根据路径删除指定的目录或文件
	 * 
	 * @param sPath
	 *            要删除的目录或文件
	 * @return 删除成功返回 true，否则返回 false。
	 */
	public static boolean DeleteFolder(String sPath) {
		boolean flag = false;
		File file = new File(sPath);
		// 判断目录或文件是否存在
		if (!file.exists()) { // 不存在返回 false
			return flag;
		} else {
			// 判断是否为文件
			if (file.isFile()) { // 为文件时调用删除文件方法
				return deleteFile(sPath);
			} else { // 为目录时调用删除目录方法
				return deleteDirectory(sPath);
			}
		}
	}

	/**
	 * 删除单个文件
	 * 
	 * @param sPath
	 *            被删除文件的文件名
	 * @return 单个文件删除成功返回true，否则返回false
	 */
	public static boolean deleteFile(String sPath) {
		boolean flag = false;
		File file = new File(sPath);
		// 路径为文件且不为空则进行删除
		if (file.isFile() && file.exists()) {
			file.delete();
			flag = true;
		}
		return flag;
	}

	/**
	 * 删除目录（文件夹）以及目录下的文件
	 * 
	 * @param sPath
	 *            被删除目录的文件路径
	 * @return 目录删除成功返回true，否则返回false
	 */
	public static boolean deleteDirectory(String sPath) {
		// 如果sPath不以文件分隔符结尾，自动添加文件分隔符
		if (!sPath.endsWith(File.separator)) {
			sPath = sPath + File.separator;
		}
		File dirFile = new File(sPath);
		// 如果dir对应的文件不存在，或者不是一个目录，则退出
		if (!dirFile.exists() || !dirFile.isDirectory()) {
			return false;
		}
		boolean flag = true;
		// 删除文件夹下的所有文件(包括子目录)
		File[] files = dirFile.listFiles();
		for (int i = 0; i < files.length; i++) {
			// 删除子文件
			if (files[i].isFile()) {
				flag = deleteFile(files[i].getAbsolutePath());
				if (!flag)
					break;
			} // 删除子目录
			else {
				flag = deleteDirectory(files[i].getAbsolutePath());
				if (!flag)
					break;
			}
		}
		if (!flag)
			return false;
		// 删除当前目录
		if (dirFile.delete()) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 按照日期得到日期文件夹路径,格式yyyy/MMdd/
	 * 
	 * @param date
	 * @return 如:2015/0429/
	 */
	public static String getUploadPathByDate(Date date) {
		if (date == null) {
			date = new Date();
		}
		// 按照日期分文件夹保存,格式yyyy/MMdd
		String datePath = DateUtil.getYearStr(date) + "/"
				+ DateUtil.getMonthStr(date) + DateUtil.getDayStr(date) + "/";

		return datePath;
	}

}
